package batch;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import smoothing.Smoother;
import smoothing.SmootherFactory;
import dao.FileIO;

public class BatchSmoother {

	public void proceed(String[] args) {
		
		String fileListFile = args[0];
		String smoothingType = args[1];
		
		List<String> remain = new ArrayList<String>(args.length - 2);
		for(int i = 2; i < args.length; i++) {
			remain.add(args[i]);
		}
		
		Smoother smoother = SmootherFactory.getSmoother(smoothingType);
		smoother.initialize(remain);
		
		List<String> lines = FileIO.readFile(fileListFile);
		Iterator<String> itr = lines.iterator();
		itr.next();
		itr.next();
		
		while(itr.hasNext()) {
			String [] tokens = itr.next().split(" ");
			String resultFile = tokens[2];
			String smoothedFile = tokens[3];
			proceedOneFile(resultFile, smoothedFile, smoother);
		}
	}
	
	protected void proceedOneFile(String resultFile, String smoothedFile, Smoother smoother) {
		List<String> lines = FileIO.readFile(resultFile);
		
		Iterator<String> itr = lines.iterator();
		itr.next();
		List<Integer> original = new ArrayList<Integer>(lines.size() - 1);
		List<Double> values = new ArrayList<Double>(lines.size() - 1);
		while(itr.hasNext()) {
			String line = itr.next();
			int label = line.charAt(0) - '0';
			double value = Double.parseDouble(line.substring(2, line.length() - 2));
			original.add(label);
			values.add(value);
		}
		
		smoother.smooth(original, values);
		values = normalize(values);
		
		List<String> list = new LinkedList<String>();
		Iterator<Integer> lItr = original.iterator();
		Iterator<Double> vItr = values.iterator();
		
		list.add("label 1 0\n");
		
		while(lItr.hasNext()) {
			int label = lItr.next();
			double value = vItr.next();
			list.add(label + " " + value + " 0\n");
		}
		
		FileIO.writeFile(smoothedFile, list);
	}
	
	protected List<Double> normalize(List<Double> list) {
		List<Double> result = new ArrayList<Double>(list.size());
		double max = Collections.max(list);
		double min = Collections.min(list);
		if(max == min) {
			for(int i = 0; i < list.size(); i++) {
				result.add(0.5);
			}
		} else {
			for(double value : list) {
				double normalized = (value - min) / (max - min);
				result.add(normalized);
			}
		}
		return result;
	}
	
	public static void main(String[] args) {
		BatchSmoother m = new BatchSmoother();
		m.proceed(args);
	}
}
